__author__ = 'slate'
''' Handles customer creation and customer pools
on each daybegin and after buying a brothel generate_pool must be called
on each day get_pool gives back the customers for the brothel
when doing a job, the following happens:
	customer.atbrothel(time) is True, so he is ready to be occupied at this time
	job begins
	customer.occuped=True (or anything that evaluates to it)
	periods can happen inbetween.
	customer pays: c.cash decreases
	customer satisfaction level increases, decreases
	customer.occupied=False
	job ends
'''
import random
from .time import Time

# This should be in some util common module like wlist...

#static customer pools for each brothel's town, this should be saved.
pools = dict()

#FIXME fetishes, aversions, cabaret affection, alcohol affections, saving, loading
customer_template=[(dict(level=0, occupation='Munjib',payperiod=1,paychance=10,pay=(10,30)),),#0 level templates
				   (dict(level=1, occupation="Ra'if",payperiod=7,paychance=20,pay=(50,100)),),
				   (dict(level=2, occupation="Sadiq",payperiod=30,paychance=30,pay=(300,450)),),
				   (dict(level=3, occupation="Carruther",payperiod=150,paychance=80,pay=(1000,2000)),)]


#should not be instanciated outside of this module
class Customer(object):
	levels=range(5)
	def __init__(self,**kwargs):
		self.__dict__.update(kwargs) # template attributes

		#runtime attributes
		#TODO random names
		self.name=self.occupation
		self.occupied=False # if the customer is occupied in a job now. The job sets it to True and false or equivalent.
		self.cash = 0 # how much he actualy has everybody begins with 0
		self.satisfaction = 0 # not set and not read here at all
		self.firstpay = None # the first day he gets the pay

		self.appears=False # if the customer on the given day appears
		self.appearsat=[] # list of times when the customer appears

	def atbrothel(self,time):
		"customer is at the brothel waiting for some occupation"
		return time in self.appearsat and not self.occupied



def generate_pool(brothel):
	'''Generates all possible customers for the brothel and saves it in pools.
	Called once on brothel creation and new game'''
	if brothel in pools:
		return pools[brothel]

	customer_number=2000 # how many customer in the pool FIXME should be set in the brothel
	level_distribution=(70,20,0,0,0) #distiribution weights of customers by level FIXME should be set in the brothel
	customers=set()
	for level in range(5):
		count=level_distribution[level]*customer_number/sum(level_distribution)
		for _ in range(count):
			c=Customer(**random.choice(customer_template[level]))
			c.firstpay=random.randint(0,c.payperiod)
			customers.add(c)
	pools[brothel]=customers

def _chance():
	return random.randint(0,100)

def get_pool(brothel,day):
	'''returns the customers visiting the brothel on this day.
	Regenerates on each day sets the atbrothel attribute of the customer
	brothel: brothel instance
	day: daycounter integer
	'''
	shiftchances=(30,50,90,70)#%chances of customer on each shift FIXME must be set in the brothel
	advertising=100 #%chance of customer comming FIXME must be set in the brothel
	returned_customers=set()
	for customer in pools[brothel]:
		if customer.occupied: # if the occupation gets over shift's end
			returned_customers.add(customer)
			continue
		customer.appears=False
		customer.appearsat=[]
		if (day % customer.payperiod!=customer.firstpay \
			or _chance() > customer.paychance) \
			and customer.cash==0:
				continue # no payday, no cash
		customer.cash+=random.randint(*customer.pay)

		if _chance()>advertising: continue
		for shift in Time.shifts:
			if _chance() > shiftchances[shift]:continue
			period=random.choice(Time.periods) #flat chance of appearing once in a shift
			customer.appearsat.append(Time(day,shift,period))
			customer.appears=True
			returned_customers.add(customer)
	return returned_customers # the same as {c for c in pools[brothel] if c.appears}

def _pool_statistics(brothel):
	from collections import defaultdict
	appears=defaultdict(dict)
	sumc=set()
	for shift in (Time.shifts):# :
		for period in Time.periods:
			for customer in pools[brothel]:
				if customer.atbrothel(Time(0,shift,period)):
					appears[shift,period][customer.level]=appears[shift,period].get(customer.level,0)+1
					sumc.add(customer)
	for shift in (Time.shifts):
		for period in Time.periods:
			ret="Period:"+str(period)+"---"
			for level in customer.levels:
				ret+=str(appears[shift,period].get(level,0))+"("+str(level)+")"+"|"
			print ret
	print "All customers: " + str(len(sumc))


if __name__=="__main__":
	#python -m lib.data.customers
	class Brothel(object):
		def __init__(self, **kwds):
			self.__dict__.update(kwds)
		def __hash__(self):
			return hash(self.name)

	b=Brothel(name="some")
	generate_pool(b)
	p=get_pool(b,0)
	_pool_statistics(b)
